package models

import (
	"context"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/beego/beego/v2/client/orm"
	beego "github.com/beego/beego/v2/server/web"
)

type Order struct {
	Id       int64  `form:"id" json:"id" orm:"column(id);pk;auto"`
	ShopId   int    `form:"shop_id" json:"shop_id" orm:"column(shop_id)"`
	Uid      int    `gorm:"column:customer_id" form:"customer_id" json:"customer_id" orm:"column(customer_id)"`
	Nickname string `form:"nickname" json:"nickname" orm:"column(nickname)"`
	Address  string `form:"address" json:"address" orm:"column(address)"`
	InitTime string `form:"init_time" json:"init_time" orm:"type(datetime)"`
}

type OrderRet struct {
	Id       int64  `form:"id" json:"id" orm:"column(id);pk;auto"`
	Nickname string `form:"nickname" json:"nickname" orm:"column(nickname)"`
	Address  string `form:"address" json:"address" orm:"column(address)"`
	InitTime string `form:"init_time" json:"init_time" orm:"type(datetime)"`
}

func init() {
	orm.RegisterModel(new(Order))
}

// TableName
// Desc: 绑定默认表名
// User: zouqihui
// Date: 2022-12-06 12:00:51
// @receiver o
// @return string
func (o *Order) TableName() string {
	return "orders"
}

// RawQuery
// Desc: 原生查询
// User: zouqihui
// Date: 2022-12-08 10:20:47
// @receiver o
// @return ret
// @return err
func RawQuery() (ret interface{}, err error) {
	//orm := orm.NewOrm()

	//查询
	//order := &Order{}
	//err2 := orm.Raw("select id,nickname from orders where id = ? ", 5).QueryRow(order)
	//if err2 != nil {
	//	fmt.Println("查询失败")
	//	return Order{}, err2
	//}
	//return order, err2

	//批量查询
	/*list := &[]Order{}//
	num, err2 := orm.Raw("select id,nickname from orders where id > ? ", 5).QueryRows(list)
	if num > 0 {
		fmt.Println("查询行数：" + strconv.FormatInt(num, 10))
	}
	return list, err2*/

	//插入
	//res, err2 := orm.Raw("insert into orders(shop_id,customer_id,nickname,address,init_time) values(1001,666,'王五','xxx','2022-12-08 11:00:36')").Exec()
	//if err2 != nil {
	//	return nil, err2
	//}
	//// 插入数据的自增id
	//if id, err3 := res.LastInsertId(); err3 == nil {
	//	fmt.Println(id)
	//	return id, err3
	//}

	//更新
	/*res, err2 := orm.Raw("update orders set nickname=?,address=? where id=?", "laoliu", "gzhou", 30).Exec()
	if err2 != nil {
		return nil, err2
	}
	if rows, err3 := res.RowsAffected(); err3 == nil {
		fmt.Println("affected rows :" + string(rows))
		return rows, err3
	}*/

	//删除
	/*res, err2 := orm.Raw("delete from orders where id=?", 29).Exec()
	if err2 != nil {
		return nil, err2
	}
	if rows, err3 := res.RowsAffected(); err3 == nil {
		fmt.Println("affected rows: " + string(rows))
		return rows, err3
	}*/

	driverName, _ := beego.AppConfig.String("db_driver_name")
	qd, _ := orm.NewQueryBuilder(driverName)
	qd.Select("id", "nickname").From(new(Order).TableName()).Where("id > ?")
	//qd.Select("id", "nickname").From(new(Order).TableName()).Where("id > ?").Limit(3).Offset(5)
	sql := qd.String()
	o := orm.NewOrm()

	list := &[]OrderRet{}
	var num int64
	num, err = o.Raw(sql, 5).QueryRows(list)
	fmt.Println(list)
	fmt.Println("查询行数：" + strconv.FormatInt(num, 10))
	return list, err

	return
}

// GormQuery
// Desc:
// User: zouqihui
// Date: 2022-12-08 18:29:28
// @param id
// @return data
// @return err
func GormQuery(id int64) (data interface{}, err error) {

	//查询
	/*order := &Order{}
	order.Id = id
	first := GormDB.First(order)

	cnt := int(first.RowsAffected)
	fmt.Println(cnt)
	err = first.Error
	return order, err*/

	//新建一个空map，Select就能查询指定字段
	//orders := &[]map[string]interface{}{}
	//find := GormDB.Select("id", "nickname").Table(new(Order).TableName()).Where("id > 5").Find(orders)
	//err = find.Error
	//return orders, err

	//var cnt int64
	//GormDB.Select("id", "nickname").Table(new(Order).TableName()).Where("id > 5").Count(&cnt)
	//return cnt, err

	//更新
	/*update := GormDB.Model(&Order{}).Where("id=?", 5).Where("shop_id=?", 0).Update("nickname", "liuliu2")
	num := update.RowsAffected
	fmt.Println(num)*/

	//多字段更新
	/*order := Order{Id: 5}
	updates := GormDB.Model(&order).Updates(Order{
		ShopId:   123,
		Uid:      666,
		Nickname: "laoliu2",
		Address:  "的是覅偶记",
		InitTime: "2022-12-09 10:38:58",
	})
	fmt.Println(updates.RowsAffected)*/

	//插入
	/*order := Order{
		ShopId:   111,
		Uid:      222,
		Nickname: "333",
		Address:  "444",
		InitTime: "2022-12-09 11:25:23",
	}
	create := GormDB.Table(new(Order).TableName()).Create(&order)
	fmt.Println(create.RowsAffected)*/

	//批量插入
	/*orders := []Order{
		{
			ShopId:   1112,
			Uid:      2222,
			Nickname: "333",
			Address:  "444",
			InitTime: "2022-12-09 11:25:23",
		},
		{
			ShopId:   1113,
			Uid:      2224,
			Nickname: "3334",
			Address:  "4444",
			InitTime: "2022-12-09 11:26:57",
		},
	}
	creates := GormDB.Table(new(Order).TableName()).Create(&orders)
	fmt.Println(creates.RowsAffected)*/

	//删除
	//order := Order{Id: 36}
	//tx := GormDB.Table(new(Order).TableName()).Delete(&order)
	//tx := GormDB.Where("id=?", 35).Delete(&Order{})
	//tx := GormDB.Delete(&Order{}, []int{34, 33})
	//fmt.Println(tx.RowsAffected)

	//var orders []OrderRet
	//var orders []map[string]interface{}
	//scan := GormDB.Raw("select id,nickname from orders where id > ? ", 5).Scan(&orders)
	//fmt.Println(orders)

	//var order OrderRet
	//order := map[string]interface{}{}
	//scan := GormDB.Raw("select id,nickname from orders where id = ? ", 5).Scan(&order)
	//fmt.Println(order)
	//fmt.Println(scan.RowsAffected)

	//事务
	tx := GormDB.Begin()
	order := Order{
		ShopId:   666,
		Uid:      777,
		Nickname: "333",
		Address:  "444",
		InitTime: "2022-12-09 18:27:25",
	}
	create := tx.Table(new(Order).TableName()).Create(&order)
	if create.Error != nil {
		tx.Rollback()
	} else {
		tx.Commit()
		fmt.Println(create.RowsAffected)
	}

	return
}

func AddData(order *Order) (data interface{}, err error) {
	o := orm.NewOrm()
	//order := Order{}
	//order.ShopId = 1
	//order.Uid = 1002
	//order.Nickname = "zhangsan"
	//order.Address = "深圳南山区"
	//order.InitTime = time.Now()
	//fmt.Println(order)
	//id, err = o.Insert(order)
	//return

	//if err != nil {
	//	//fmt.Println("插入失败")
	//	return id,err
	//} else {
	//	return id, err
	//}

	//自动事务
	err = o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
		order := &Order{}
		order.ShopId = 1001
		order.Uid = 777
		order.Nickname = "zhangsan"
		order.Address = "深圳南山区"
		order.InitTime = time.Now().Format("2006-01-02 15:04:05")

		id, err := txOrm.Insert(order)
		fmt.Println("insert Id: " + strconv.Itoa(int(id)))

		if err != nil {
			return err
		}

		order.Id = id
		order.Nickname = "qiqiqi" + time.Now().Format("2006-01-02 15:04:05")
		rows, err := txOrm.Update(order)
		fmt.Println("update rows: " + strconv.Itoa(int(rows)))

		return err
	})

	if err != nil {
		return 0, err
	}

	return
}

// DeleteData
// Desc: 删除
// User: zouqihui
// Date: 2022-12-06 18:44:46
// @param id
// @return rows
// @return err
func DeleteData(id int64) (rows int64, err error) {
	order := &Order{Id: id}
	o := orm.NewOrm()
	if err = o.Read(order); err == nil {
		rows, err = o.Delete(order, "Id")
		if err != nil {
			return 0, err
		}
	}
	return
}

// GetData
// Desc: 获取数据
// User: zouqihui
// Date: 2022-12-06 14:18:08
// @param id
// @return Order
// @return error
func GetData(id int64) (v Order, err error) {
	v = Order{Id: id}
	orm := orm.NewOrm()
	err = orm.Read(&v)
	return
}

// BulkData
// Desc: 批量插入
// User: zouqihui
// Date: 2022-12-07 10:54:28
// @return nums
// @return err
func BulkData() (nums int64, err error) {

	t := time.Now()
	t.Format("Y-m-d H:M:S")

	return
	//orders := []Order{
	//	{ShopId: 101, Uid: 1001, Nickname: "xxx1", Address: "xxx111", InitTime: time},
	//	{ShopId: 102, Uid: 1002, Nickname: "xxx1", Address: "xxx222", InitTime: time.Now()},
	//}
	//orm := orm.NewOrm()
	//nums, err = orm.InsertMulti(len(orders), orders)
	//return
}

// UpdateData
// Desc:更新数据
// User: zouqihui
// Date: 2022-12-07 11:46:58
// @param data
// @return rows
// @return err
func UpdateData(data *Order) (rows int64, err error) {
	orm := orm.NewOrm()
	rows, err = orm.Update(data, "ShopId", "Uid", "Nickname", "Address", "InitTime")
	if err != nil {
		return 0, err
	}
	return
}

// AddOrder insert a new Order into database and returns
// last inserted Id on success.
func AddOrder(m *Order) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

// GetOrderById retrieves Order by Id. Returns error if
// Id doesn't exist
func GetOrderById(id int64) (v *Order, err error) {
	o := orm.NewOrm()
	v = &Order{Id: id}
	if err = o.QueryTable(new(Order)).Filter("Id", id).RelatedSel().One(v); err == nil {
		return v, nil
	}
	return nil, err
}

// GetAllOrder retrieves all Order matches certain condition. Returns empty list if
// no records exist
func GetAllOrder(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Order))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Order
	qs = qs.OrderBy(sortFields...).RelatedSel()
	if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateOrder updates Order by Id and returns error if
// the record to be updated doesn't exist
func UpdateOrderById(m *Order) (err error) {
	o := orm.NewOrm()
	v := Order{Id: m.Id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteOrder deletes Order by Id and returns error if
// the record to be deleted doesn't exist
func DeleteOrder(id int64) (err error) {
	o := orm.NewOrm()
	v := Order{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Order{Id: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
